package online.longzipeng.mywebdemo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import online.longzipeng.mywebdemo.entity.Comment;
import online.longzipeng.mywebdemo.mapper.CommentMapper;
import online.longzipeng.mywebdemo.mapper.UserMapper;
import online.longzipeng.mywebdemo.pojo.vo.CommentVo;
import online.longzipeng.mywebdemo.pojo.vo.UserVo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author: lzp
 * @description: 评论接口优化案例
 * @Date: 2022/12/6
 */
@Slf4j
@SpringBootTest(classes = MyWebDemoApplication.class,
		webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommentInterfaceOptimizationDemo {

	@Autowired
	private UserMapper userMapper;
	@Autowired
	private CommentMapper commentMapper;

	private static final int size = 900;

	/**
	 * 获取评论列表，每条评论包含作者和回复目标  2629 毫秒  300条数据
	 * 5011 毫秒  900条
	 */
	@Test
	public void listCommentDemo1() {
		long start = System.currentTimeMillis();
		List<Comment> comments = commentMapper.selectList(Wrappers.<Comment>lambdaQuery()
				.orderByDesc(Comment::getCreateTime)
				.last("LIMIT " + size));
		List<CommentVo> commentVos = comments.stream().map(c -> {
			CommentVo cv = new CommentVo();
			BeanUtil.copyProperties(c, cv);
			cv.setAuthor(userMapper.getUserVoById(c.getUid()));
			if (ObjectUtil.isNotNull(c.getToUid())) {
				cv.setToUser(userMapper.getUserVoById(c.getToUid()));
			}
			return cv;
		}).collect(Collectors.toList());
		long costTime = System.currentTimeMillis() - start;

		System.out.printf("共花费了 %s 毫秒\n",costTime);

	}

	/**
	 * 优化一： 用户只查一次   1036 毫秒 300条数据
	 * 1150 毫秒  900条
	 */
	@Test
	public void listCommentDemo2() {
		long start = System.currentTimeMillis();
		List<Comment> comments = commentMapper.selectList(Wrappers.<Comment>lambdaQuery()
				.orderByDesc(Comment::getCreateTime)
				.last("LIMIT " + size));
		// 取出评论列表关联的所有用户的uid
		Set<Integer> uids = new HashSet<>();
		comments.forEach(c->{
			uids.add(c.getUid());
			if (ObjectUtil.isNotNull(c.getToUid())) {
				uids.add(c.getToUid());
			}
		});
		// 查出所有用户
		List<UserVo> userVos = userMapper.listUserVoByIds(uids);

		List<CommentVo> commentVos = comments.stream().map(c -> {
			CommentVo cv = new CommentVo();
			BeanUtil.copyProperties(c, cv);
			for (UserVo userVo : userVos) {
				if (ObjectUtil.equal(userVo.getId(),c.getUid())) {
					cv.setAuthor(userVo);
				}
				if (ObjectUtil.equal(userVo.getId(),c.getToUid())) {
					cv.setToUser(userVo);
				}
			}
			return cv;
		}).collect(Collectors.toList());

		long costTime = System.currentTimeMillis() - start;

		System.out.printf("共花费了 %s 毫秒\n",costTime);

	}

	/**
	 * 优化二： map优化循环 用户只查一次   1044 毫秒 300条数据
	 * 1137 毫秒  900条
	 */
	@Test
	public void listCommentDemo3() {
		long start = System.currentTimeMillis();
		List<Comment> comments = commentMapper.selectList(Wrappers.<Comment>lambdaQuery()
				.orderByDesc(Comment::getCreateTime)
				.last("LIMIT " + size));
		// 取出评论列表关联的所有用户的uid
		Set<Integer> uids = new HashSet<>();
		comments.forEach(c->{
			uids.add(c.getUid());
			if (ObjectUtil.isNotNull(c.getToUid())) {
				uids.add(c.getToUid());
			}
		});
		// 查出所有用户
		List<UserVo> userVos = userMapper.listUserVoByIds(uids);

		Map<Integer, UserVo> map = userVos.stream().collect(Collectors.toMap(UserVo::getId, o -> o, (o1, o2) -> o1));

		List<CommentVo> commentVos = comments.stream().map(c -> {
			CommentVo cv = new CommentVo();
			BeanUtil.copyProperties(c, cv);
			cv.setAuthor(map.get(c.getUid()));
			cv.setToUser(map.get(c.getToUid()));
			return cv;
		}).collect(Collectors.toList());

		long costTime = System.currentTimeMillis() - start;

		System.out.printf("共花费了 %s 毫秒\n",costTime);

	}

}
